#pragma once

#include <mcp/config.h>
#include <mcp/forward.h>
#include <mcp/json/value.h>

#include <cstdint>
#include <string>
#include <vector>
#include <map>
#include <chrono>

namespace mcp {
namespace types {

/// @brief Type aliases for basic types
using RequestId = int64_t;
using ProgressToken = int64_t;
using Cursor = std::string;

/// @brief JSON-RPC request with parameters
template<typename ParamsT, typename MethodT>
class Request {
public:
    MethodT method;
    ParamsT params;
    RequestId id;

    Request() = default;
    Request(MethodT method, ParamsT params, RequestId id)
        : method(std::move(method)), params(std::move(params)), id(std::move(id)) {}
};

/// @brief JSON-RPC notification with parameters
template<typename ParamsT, typename MethodT>
class Notification {
public:
    MethodT method;
    ParamsT params;

    Notification() = default;
    Notification(MethodT method, ParamsT params)
        : method(std::move(method)), params(std::move(params)) {}
};

/// @brief Request metadata for progress tracking
struct RequestMeta {
    mcp::json::optional<ProgressToken> progress_token;
    std::map<std::string, json::Value> extra_data;
};

/// @brief Notification metadata
struct NotificationMeta {
    std::map<std::string, json::Value> extra_data;
};

/// @brief Paginated request parameters
struct PaginatedRequestParams {
    mcp::json::optional<Cursor> cursor;
};

/// @brief Content block types
enum class ContentType {
    Text,
    Image,
    EmbeddedResource,
    Audio,
    Video
};

/// @brief Base content block
struct ContentBlock {
    ContentType type;

    ContentBlock(ContentType type);
    virtual ~ContentBlock() = default;
};

/// @brief Text content
struct TextContent : ContentBlock {
    std::string text;

    TextContent();
    explicit TextContent(std::string text);
};

/// @brief Image content
struct ImageContent : ContentBlock {
    std::string data;
    std::string mime_type;

    ImageContent();
    ImageContent(std::string data, std::string mime_type);
};

/// @brief Resource definition
struct Resource {
    std::string uri;
    std::string name;
    mcp::json::optional<std::string> description;
    std::string mime_type = "text/plain";

    bool operator==(const Resource& other) const;
};

/// @brief Embedded resource content
struct EmbeddedResource : ContentBlock {
    Resource resource;

    EmbeddedResource();
    explicit EmbeddedResource(Resource resource);
};

/// @brief Resource template with URI pattern
struct ResourceTemplate {
    std::string uri_template;
    std::string name;
    mcp::json::optional<std::string> description;
    std::vector<std::string> arguments;
};

/// @brief Tool definition
struct Tool {
    std::string name;
    std::string description;
    json::Schema input_schema;
    mcp::json::optional<json::Schema> output_schema;

    bool operator==(const Tool& other) const;
};

/// @brief Tool annotation for UI hints
struct ToolAnnotations {
    mcp::json::optional<std::string> title;
    mcp::json::optional<std::string> description_hint;
    mcp::json::optional<bool> destructive_hint;
    mcp::json::optional<bool> idempotent_hint;
    mcp::json::optional<bool> open_world_hint;
};

/// @brief Prompt argument
struct PromptArgument {
    std::string name;
    mcp::json::optional<std::string> description;
    bool required = false;
};

/// @brief Prompt definition
struct Prompt {
    std::string name;
    mcp::json::optional<std::string> description;
    std::vector<PromptArgument> arguments;
};

/// @brief Prompt message role
enum class PromptRole {
    User,
    Assistant,
    System
};

/// @brief Prompt message
struct PromptMessage {
    PromptRole role;
    std::shared_ptr<ContentBlock> content;
};

/// @brief Sampling message
struct SamplingMessage {
    PromptRole role;
    std::shared_ptr<ContentBlock> content;
};

/// @brief LLM sampling options
struct SamplingOptions {
    int64_t max_tokens = 1000;
    double temperature = 0.7;
    mcp::json::optional<std::string> stop_sequence;
    mcp::json::optional<std::vector<std::string>> stop_sequences;
};

/// @brief Progress notification
struct ProgressNotification {
    ProgressToken token;
    double progress;
    mcp::json::optional<double> total;
    mcp::json::optional<std::string> message;
};

/// @brief Elicitation result
struct ElicitationResult {
    enum class Action {
        Accept,
        Decline,
        Cancel
    };

    Action action;
    mcp::json::optional<json::Value> data;
    mcp::json::optional<std::string> validation_error;
};

/// @brief Logging level
enum class LogLevel {
    Debug,
    Info,
    Warning,
    Error
};

/// @brief Logging message
struct LoggingMessage {
    LogLevel level;
    std::string message;
    mcp::json::optional<std::string> logger_name;
    mcp::json::optional<std::chrono::system_clock::time_point> timestamp;

    LoggingMessage(LogLevel level, std::string message);
};

/// @brief Resource list changed notification
struct ResourceListChangedNotification {
    mcp::json::optional<std::vector<std::string>> resources;
};

/// @brief Tool list changed notification
struct ToolListChangedNotification {
    mcp::json::optional<std::vector<std::string>> tools;
};

/// @brief Prompt list changed notification
struct PromptListChangedNotification {
    mcp::json::optional<std::vector<std::string>> prompts;
};

} // namespace types
} // namespace mcp